package org.activiti.designer.test;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.io.FileInputStream;

import org.activiti.engine.FormService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.ManagementService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.identity.Group;
import org.activiti.engine.identity.User;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.db.DbSqlSession;
import org.activiti.engine.impl.db.DbSqlSessionFactory;
import org.activiti.engine.impl.persistence.entity.UserEntity;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.ActivitiRule;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
//@RunWith(SpringJUnit4ClassRunner.class)
public class ProcessTestSubProcess {

	private String filename = "D:/Workspaces/qm/activiti-simple/src/main/resources/diagrams/SubProcess.bpmn";

	@Rule
	public ActivitiRule activitiRule = new ActivitiRule();
	public IdentityService identityService = null;
	public RuntimeService runtimeService = null;
	public RepositoryService repositoryService = null;
	TaskService taskService;

	protected ProcessEngine processEngine;
	@Autowired
	public ProcessEngineConfiguration processEngineConfiguration;
	protected HistoryService historyService = null;
	protected FormService formService = null;
	protected ManagementService managementService = null;

	UserEntity admin;
	UserEntity user1;
	UserEntity user2;
	UserEntity user3;
	UserEntity user4;
	Group leader;
	Group empDept;

	private static final long DAY = 24 * 60 * 60 * 1000;

	public void initData() {
		admin = (UserEntity) identityService.newUser("admin");
		{
			admin.setFirstName("admin");
			admin.setLastName("Admin");
			admin.setPassword("123456");
			admin.setEmail("admin@act.com");
		}
		user1 = (UserEntity) identityService.newUser("liTian");
		{
			user1.setFirstName("Tian");
			user1.setLastName("Li");
			user1.setPassword("123456");
			user1.setEmail("liTian@act.com");
		}
		user2 = (UserEntity) identityService.newUser("liTian2");
		{
			user2.setFirstName("Tian2");
			user2.setLastName("Li2");
			user2.setPassword("123456");
			user2.setEmail("liTian@act.com");
		}
		user3 = (UserEntity) identityService.newUser("liTian3");
		{
			user3.setFirstName("Tian3");
			user3.setLastName("Li3");
			user3.setPassword("123456");
			user3.setEmail("liTian@act.com");
		}
		user4 = (UserEntity) identityService.newUser("liTian4");
		{
			user4.setFirstName("Tian4");
			user4.setLastName("Li4");
			user4.setPassword("123456");
			user4.setEmail("liTian@act.com");
		}

		leader = identityService.newGroup("Leader");
		{
			leader.setName("领导");
		}
		empDept = identityService.newGroup("EmpDept");
		{
			empDept.setName("员工");
		}

		identityService.saveUser(admin);
		identityService.saveUser(user1);
		identityService.saveUser(user2);
		identityService.saveUser(user3);
		identityService.saveUser(user4);

		identityService.saveGroup(leader);
		identityService.saveGroup(empDept);

		identityService.createMembership(admin.getId(), leader.getId());
		identityService.createMembership(user1.getId(), empDept.getId());

		System.out.println("---------BASE DATA START-------------");
		System.out.println("ADMIN:" + admin.getId());
		System.out.println("EMP:" + user1.getId());
		System.out.println("EMP:" + user2.getId());
		System.out.println("EMP:" + user3.getId());
		System.out.println("EMP:" + user4.getId());

		System.out.println("---------BASE DATA END---------------");
	}

	/**
	 * 开启一个mybatis的session，切记要关闭
	 */
	protected SqlSession openSession() {
		ProcessEngineConfigurationImpl peci = (ProcessEngineConfigurationImpl) processEngineConfiguration;
		DbSqlSessionFactory dbSqlSessionFactory = (DbSqlSessionFactory) peci
				.getSessionFactories().get(DbSqlSession.class);
		SqlSessionFactory sqlSessionFactory = dbSqlSessionFactory
				.getSqlSessionFactory();
		return sqlSessionFactory.openSession();
	}

	@Test
	public void startProcess() throws Exception {
		identityService = activitiRule.getIdentityService();
		runtimeService = activitiRule.getRuntimeService();
		repositoryService = activitiRule.getRepositoryService();
		taskService = activitiRule.getTaskService();
		processEngine = activitiRule.getProcessEngine();
		historyService = processEngine.getHistoryService();

		System.out.println(processEngineConfiguration);
		
		
		
		repositoryService
				.createDeployment()
				.addInputStream("SubProcess.bpmn20.xml",
						new FileInputStream(filename)).deploy();

		initData();

		String initiatorUserId = admin.getId();

		List<String> list = new ArrayList<String>();
		list.add("aaaa");
		list.add("bbbb");
		list.add("cccc");
		list.add("dddd");

		Map<String, Object> variableMap = new HashMap<String, Object>();

		variableMap.put("list", list);
		// 设置liTian为流程发起人
		identityService.setAuthenticatedUserId(initiatorUserId);
		ProcessInstance processInstance = runtimeService
				.startProcessInstanceByKey("myProcess", "LEAVE001", variableMap);

		assertNotNull(processInstance.getId());

		findByDefinitionKey("usertask1");

		findCandidateByGroup(leader.getId());
		findCandidateByGroup(empDept.getId());

		findCandidateByUser(admin.getId());
		findCandidateByUser(user1.getId());

		groupClaimTask(empDept.getId(), user1.getId());
		groupClaimTask(empDept.getId(), user2.getId());
		groupClaimTask(empDept.getId(), user3.getId());
		groupClaimTask(empDept.getId(), user4.getId());

		// 添加任务 试试
		variableMap = findTaskVariables(findByDefinitionKey("usertask1").get(0)
				.getId());

		List<Task> tasks = taskService.createTaskQuery()
				.taskDefinitionKey("usertask1")
				.processInstanceId(processInstance.getId()).list();

		for (Task task : tasks) {
			System.out.println(task.getId());
		}

		userHandleTask(processInstance.getId(), user1.getId(), true);
		userHandleTask(processInstance.getId(), user2.getId(), true);
		userHandleTask(processInstance.getId(), user3.getId(), true);
		userHandleTask(processInstance.getId(), user4.getId(), true);
	}

	public void initiatorUserClaimTask(String userId) {
		List<Task> tasks = findCandidateByUser(userId);
		if (tasks.size() > 0) {
			System.out.println("用户【" + userId + "】 签收：" + tasks.get(0).getId());
			taskService.claim(tasks.get(0).getId(), userId);
		}
	}

	public void userHandleTask(String processInstanceId, String userId,
			boolean pass) {

		List<Task> tasks = findTaskByAssignee(userId);
		if (tasks.size() > 0) {
			Task task = tasks.get(0);

			userViewTask(task.getId());

			Map<String, Object> variableMap = findTaskVariables(task.getId());

			variableMap.put("continue", pass);

			if (pass) {
				taskService.addComment(task.getId(), processInstanceId,
						"Thanks!");

			} else {
				taskService.addComment(task.getId(), processInstanceId,
						"Leader大大，要不要这么不人道！");

				variableMap.put("leaveStartDate",
						variableMap.get("leaveStartDate"));
				variableMap.put(
						"leaveEndDate",
						new Date(((Date) variableMap.get("leaveStartDate"))
								.getTime() + (15l * DAY)));
			}

			System.out.println(task.getAssignee() + "完成任务：" + task.getId());
			identityService.setAuthenticatedUserId(userId);
			taskService.complete(task.getId(), variableMap);
		}

	}

	public void groupClaimTask(String groupId, String userId) {

		List<Task> tasks = findCandidateByGroup(groupId);

		if (tasks.size() > 0) {
			System.out.println("组织【" + groupId + "】 " + " 用户【" + userId
					+ "】 签收：" + tasks.get(0).getId());
			taskService.claim(tasks.get(0).getId(), userId);
		}

	}

	public void userViewTask(String taskId) {
		System.out.println("查看了任务【" + taskId + "】");
		findTaskVariables(taskId);

	}

	public void leaderHandleTask(String processInstanceId, String userId,
			boolean pass) {

		List<Task> tasks = findTaskByAssignee(admin.getId());
		if (tasks.size() > 0) {
			Task task = tasks.get(0);

			userViewTask(task.getId());

			Map<String, Object> variableMap = new HashMap<String, Object>();

			variableMap.put("leadPass1", pass);

			if ((Boolean) variableMap.get("leadPass1")) {
				taskService.addComment(task.getId(), processInstanceId, "同意了");

			} else
				taskService.addComment(task.getId(), processInstanceId,
						" 假期太长 不同意");
			System.out.println(task.getAssignee() + "完成任务：" + task.getId());
			identityService.setAuthenticatedUserId(userId);
			taskService.complete(task.getId(), variableMap);
		}

	}

	public List<Task> findCandidateByGroup(String gid) {
		List<Task> tasks = taskService.createTaskQuery()
				.taskCandidateGroup(gid).list();
		for (Task task : tasks) {
			System.out.println(gid + "组 代办任务: " + task.getName());
		}
		return tasks;
	}

	public List<Task> findCandidateByUser(String uid) {
		List<Task> tasks = taskService.createTaskQuery().taskCandidateUser(uid)
				.list();

		for (Task task : tasks) {
			System.out.println(uid + " 代办任务: " + task.getName());
		}
		return tasks;
	}

	public List<Task> findByDefinitionKey(String key) {
		List<Task> tasks = taskService.createTaskQuery().taskDefinitionKey(key)
				.list();

		for (Task task : tasks) {
			System.out.println(key + " 代办任务: " + task.getName());
		}
		return tasks;
	}

	public List<Task> findTaskByAssignee(String uid) {
		List<Task> tasks = taskService.createTaskQuery().taskAssignee(uid)
				.list();
		for (Task task : tasks) {
			System.out.println(uid + " 签收的任务: " + task.getName());
		}
		return tasks;
	}

	public Map<String, Object> findTaskVariables(String taskid) {
		Map<String, Object> vars = taskService.getVariables(taskid);
		System.out.println("打印TaskID: " + taskid + " 流程变量：");
		for (String variableName : vars.keySet()) {
			Object val = vars.get(variableName);
			System.out.println("\t" + variableName + " = " + val);
		}
		System.out.println("打印结束");
		return vars;
	}

}